package com.wxxymakers.grademark.controller;

import com.wxxymakers.grademark.model.entity.WxRole;
import com.wxxymakers.grademark.model.entity.WxUser;
import com.wxxymakers.grademark.service.WxUserService;
import com.wxxymakers.grademark.utils.Const;
import com.wxxymakers.grademark.utils.RestResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.Instant;

/**
 * @AUTHOR soft
 * @DATE 2018/12/21 15:38
 * @DESCRIBE 用户控制器 包含很多用户功能
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Value("${file.upload}")
    private String upload;

    @Autowired
    private WxUserService userService;

    @PostMapping("/none/register")
    public RestResponse register(WxUser user) {
        user.setRoleId(1);
        if (userService.register(user)) {
            return RestResponse.ok(user);
        }
        return RestResponse.fail();
    }

    @PostMapping("/none/login")
    public RestResponse login(@RequestParam String username,
                              @RequestParam String password,
                              @RequestParam(required = false, defaultValue = "true") boolean remember) {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password, remember);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            return RestResponse.ok("登录成功！");
        } catch (AuthenticationException e) {
            log.error("登录失败！{}", e.getMessage());
            return RestResponse.fail(e.getMessage());
        }
    }

    /**
     * 找回密码 直接将新密码发送到用户邮箱
     *
     * @param username 用户名
     * @param email    邮箱
     */
    @PostMapping("/none/back")
    public RestResponse backPass(@RequestParam String username,
                                 @RequestParam String email) {
        WxUser user = userService.byUsername(username);
        if (user.getEmail().equals(email)) {
            WxUser wxUser = new WxUser();
            wxUser.setUsername(username);
            wxUser.setPassword(user.getJobNum());
            if (userService.change(wxUser)) {
                return RestResponse.ok("密码重置回原始密码 -> " + username);
            }
        }
        return RestResponse.fail("邮箱错误！");
    }

    /**
     * 用户个人信息修改
     * 用户只可以修改基本信息 姓名 性别 生日 电话 邮箱 密码
     *
     * @param user 用户信息
     */
    @PostMapping("/change")
    public RestResponse change(WxUser user, @SessionAttribute(Const.CURRENT_USER) WxUser wxUser) {
        user.setUsername(null);
        user.setJobNum(null);
        user.setRoleId(null);
        user.setDepartment(null);
        user.setDutyId(null);
        user.setDutyLevel(null);
        user.setNtime(null);
        user.setWtime(null);
        user.setId(wxUser.getId()); // 必须当前用户
        if (userService.change(user)) {
            WxUser byId = userService.byId(wxUser.getId());
            SecurityUtils.getSubject().getSession().setAttribute(Const.CURRENT_USER, byId);
            return RestResponse.ok();
        }
        return RestResponse.fail();
    }

    @PostMapping("/safe")
    public RestResponse safeSet(String oldPass, String newPass,
                                @SessionAttribute(Const.CURRENT_USER) WxUser user) {
        String username = user.getUsername();
        if (!userService.toHex(username, oldPass).equals(user.getPassword())) {
            return RestResponse.fail("原始密码错误！");
        }

        WxUser u = new WxUser();
        u.setId(user.getId());
        u.setUsername(username);
        u.setPassword(newPass);
        if (userService.change(u)) {
            SecurityUtils.getSubject().logout();
            return RestResponse.ok("修改成功！");
        }
        return RestResponse.fail("修改失败！");
    }

    @PostMapping("/get/{id}")
    public RestResponse get(@PathVariable int id) {
        WxUser wxUser = userService.byId(id);
        if (wxUser != null) {
            return RestResponse.ok(wxUser);
        }
        return RestResponse.fail("获取用户失败！");
    }

    @RequiresRoles(value = {"admin", "college-admin"}, logical = Logical.OR)
    @PostMapping("/page")
    public RestResponse page(@RequestParam int page,
                             @RequestParam int limit,
                             WxUser query,
                             @SessionAttribute(Const.CURRENT_USER) WxUser user) {
        if (!user.getRole().getSign().equals("admin")) {
            query.setCollageId(user.getCollageId()); // 普通管理只能看到自己学院的
        }
        Page<WxUser> userPage = userService.page(page, limit, query, true, true);
        if (userPage != null) {
            return RestResponse.ok(userPage);
        }
        return RestResponse.fail();
    }

    /**
     * 对用户进行调度 只有超级管理员可以操作
     *
     * @param user 用户调度信息
     */
    @PostMapping("/adjust")
    @RequiresRoles({"admin"})
    public RestResponse adjust(WxUser user) {
        if (user != null) {
            /*WxUser wxUser = userService.byIdNo(user.getId());
            if (wxUser.getDutyId().equals(user.getDutyId()) && wxUser.getDeptId().equals(user.getDeptId())) {
                user.setDutyId(null);
                user.setDeptId(null);
            }*/
            if (userService.change(user)) {
                return RestResponse.ok();
            }
        }
        return RestResponse.fail();
    }

    /**
     * 删除用户 仅限管理
     *
     * @param uid 用户id
     */
    @PostMapping("/delete/{uid}")
    @RequiresRoles(value = {"admin", "college-admin"}, logical = Logical.OR)
    public RestResponse delete(@PathVariable int uid,
                               @SessionAttribute(Const.CURRENT_USER) WxUser user) {
        if (uid == 1) return RestResponse.fail("系统级账号无法删除！");
        if (uid == user.getId()) {
            return RestResponse.fail("无权删除自己！");
        }
        WxUser wxUser = userService.byId(uid);
        WxRole role = wxUser.getRole();
        if (role.getSign().equals("admin") && user.getRole().getSign().equals("college-admin")) {
            return RestResponse.fail("无权越级删除！");
        }

        if (userService.delete(uid)) {
            return RestResponse.ok();
        }
        return RestResponse.fail();
    }

    /**
     * 头像
     * @param filename 头像文件
     */
    @RequestMapping("/cover/{filename}")
    public ResponseEntity<byte[]> cover(@PathVariable String filename) throws IOException {
        File file = new File(upload, filename + ".jpg");
        if (file.exists()) {
            FileInputStream in = new FileInputStream(file);
            byte[] bytes = StreamUtils.copyToByteArray(in);
            in.close();

            return ResponseEntity.status(200)
                    .contentLength(bytes.length)
                    .contentType(MediaType.IMAGE_JPEG)
                    .body(bytes);
        }
        return ResponseEntity.notFound().build();
    }

    /**
     * 头像上传
     * @param file 文件
     * @param user 当前登录用户信息
     */
    @PostMapping("/c/upload")
    public RestResponse cover(@RequestParam MultipartFile file,
                              @SessionAttribute(Const.CURRENT_USER) WxUser user) throws IOException {
        if (file != null) {
            long second = Instant.now().getEpochSecond();
            String filename = second + "_" + user.getId();
            File target = new File(upload, filename + ".jpg");
            target.getParentFile().mkdirs(); // 创建父文件夹
            file.transferTo(target);

            String cover = user.getCover();
            if (!StringUtils.isEmpty(cover)) {
                String fn = cover.substring(cover.lastIndexOf("/"));
                new File(upload, fn + ".jpg").delete(); // 删除以前的头像文件
            }

            String cUrl = "/user/cover/" + filename;
            WxUser cu = new WxUser();
            cu.setId(user.getId());
            cu.setCover(cUrl);
            userService.change(cu);
            user.setCover(cUrl);
            return RestResponse.ok(cUrl);
        }
        return RestResponse.fail();
    }
}
